<template>
  <div id="data-preview-table" class="table-data-preview">
    <!-- 多表 -->
    <a-tabs
      v-if="previewedDatasetOfTable && previewedDatasetOfTable.length > 1"
      type="card"
      :default-active-key="
        previewedDatasetOfTable && previewedDatasetOfTable.length > 0
          ? previewedDatasetOfTable[0].fileName
          : null
      "
      @change="changeTable"
    >
      <a-tab-pane
        v-for="(table, index) in previewedDatasetOfTable"
        :key="table.fileName"
        :tab="table.name"
      >
        <data-preview-table
          :head="table.head"
          :data="table.data"
          data-type="table"
          :enable-edit-title="true"
          @changeColType="changeColType"
          @change-semantic="changeSemantic"
          @title-change="(value) => handleTitleChange(index, value)"
        />
      </a-tab-pane>
    </a-tabs>
    <!-- 单表 -->
    <data-preview-table
      v-if="previewedDatasetOfTable && previewedDatasetOfTable.length === 1"
      :head="previewedDatasetOfTable[0].head"
      :data="previewedDatasetOfTable[0].data"
      data-type="table"
      :enable-edit-title="true"
      @changeColType="changeColType"
      @change-semantic="changeSemantic"
      @title-change="(value) => handleTitleChange(0, value)"
    />
  </div>
</template>

<script lang="ts">
/**
 * 表数据预览
 * @author Jinhui Hou
 */
import { Component, Vue } from 'vue-property-decorator'
import DataPreviewTable from '@/components/data/DatasetPreviewTable.vue'
import DataUploadStore from '@/store/modules/data-upload'
import { cloneDeep } from 'lodash'

@Component({
  components: {
    DataPreviewTable,
  },
})
export default class TableDataPreview extends Vue {
  // 预览数据
  public get previewedDatasetOfTable() {
    return DataUploadStore.previewedDatasetOfTable
  }
  // 当前激活的预览表
  public get activeTableFileName(): string | null {
    return DataUploadStore.activeTableFileName
  }
  // 源数据
  public get datasetData() {
    return DataUploadStore.datasetData
  }

  // 脱敏配置
  public get haveSetDesensitization() {
    return DataUploadStore.haveSetDesensitization
  }

  /**
   * 切换 激活的预览表
   */
  public changeTable(tableName: string) {
    DataUploadStore.setActiveTableFileName(tableName)
    this.getDataWithMask()
  }

  /**
   * 脱敏组件修改 是否使用类型/语义推断
   * @param type 数据类型 / 数据语义
   * @param value 是否使用推断
   */
  public toggleTypeSemanticInfer({
    type,
    value,
  }: {
    type: 'type' | 'semantic'
    value: boolean
  }) {
    if (type === 'type') {
      this.editType(value)
    } else {
      this.changePreviewDataSemantic(value)
      this.changeDatasetDataSemantic(value)
    }
  }

  /**
   * 修改数据类型
   * @param value
   */
  private editType(value: boolean) {
    DataUploadStore.previewedDatasetOfTable.forEach((table: any) => {
      this.updateTableHead(table, value)
    })
  }

  /**
   * 修改每一张表的 head
   * @param table
   * @param mark
   * @private
   */
  private updateTableHead(table: any, mark: boolean) {
    table.newHead.forEach((column: any, index: number) => {
      // 推断类型 checkbox 选中， 并且推断语义存在， 使用推断语义， 否则 varchar
      const type: string =
        mark && column.recommendType ? column.recommendType : 'varchar'
      column.type = type
      table.head.splice(index, 1, {
        ...table.head[index],
        type,
      })
    })
  }

  /**
   * 修改 previewData 每一张表是否使用推断语义
   * @param mark
   */
  public changePreviewDataSemantic(mark: boolean) {
    DataUploadStore.previewedDatasetOfTable.forEach((table: any) => {
      this.changeSemanticDataTableHead(table, mark)
    })
  }

  /**
   * 修改 datasetData 每一张表是否使用推断语义
   * @param mark
   */
  public changeDatasetDataSemantic(mark: boolean) {
    this.datasetData.forEach((table: any) => {
      this.changeSemanticDataTableHead(table, mark)
    })
  }

  /**
   * 修改每一张表的每一列 semantic 语义
   * @param table
   * @param mark
   * @private
   */
  private changeSemanticDataTableHead(table: any, mark: boolean) {
    table.newHead.forEach((column: any, index: number) => {
      const semantic: string =
        mark && column.recommendSemantic ? column.recommendSemantic : 'null'
      column.semantic = semantic
      table.head.splice(index, 1, {
        ...table.head[index],
        semantic,
      })
    })
  }

  /**
   * 修改数据列的类型， 只修改 newHead
   */
  public changeColType(value: any) {
    const index = this.datasetData.findIndex(
      (item: any) => item.fileName === this.activeTableFileName
    )
    this.datasetData[index].newHead[value.index].type = value.type
    // 上传表格文件预览数据
    this.previewedDatasetOfTable[index].newHead[value.index].type = value.type
  }

  /**
   * 语义推断与修改  修改 newHead, head
   */
  public changeSemantic(semanticInfo: { index: number; semantic: string }) {
    const { index, semantic } = semanticInfo
    // 当前激活的表
    const indexCol = this.datasetData.findIndex(
      (item: any) => item.fileName === this.activeTableFileName
    )
    this.datasetData[indexCol].newHead[index].semantic = semantic
    this.datasetData[indexCol].head.splice(index, 1, {
      ...this.datasetData[indexCol].head[index],
      semantic,
    })

    // 上传表格文件预览数据
    this.previewedDatasetOfTable[indexCol].newHead[index].semantic = semantic
    this.previewedDatasetOfTable[indexCol].head.splice(index, 1, {
      ...this.previewedDatasetOfTable[indexCol].head[index],
      semantic,
    })
  }

  /**
   * 表头文字调整
   * @param tableIndex:number 第几张表
   */
  public handleTitleChange(
    tableIndex: number,
    {
      index: columnIndex,
      newValue,
      oldValue,
    }: { index: number; newValue: string; oldValue: string }
  ) {
    this.previewedDatasetOfTable[tableIndex].newHead[
      columnIndex
    ].name = newValue
    this.datasetData[tableIndex].newHead[columnIndex].name = newValue
    // 处理返回来的数据
    this.previewedDatasetOfTable[
      tableIndex
    ].data = this.previewedDatasetOfTable[tableIndex].data.map((item: any) => {
      const newData = {
        ...item,
        [newValue]: item[oldValue],
      }
      delete newData[oldValue]
      return newData
    })
    // 源数据
    this.datasetData[tableIndex].data = this.datasetData[tableIndex].data.map(
      (item: any) => {
        const newData = {
          ...item,
          [newValue]: item[oldValue],
        }
        delete newData[oldValue]
        return newData
      }
    )
    // 处理脱敏配置
    const tableName = this.previewedDatasetOfTable[tableIndex].name
    const newData = {
      ...this.haveSetDesensitization[tableName],
      [newValue]: this.haveSetDesensitization[tableName][oldValue],
    }
    delete newData[oldValue]
    DataUploadStore.setHaveSetDesensitization({
      ...this.haveSetDesensitization,
      [tableName]: newData,
    })
  }

  /**
   * 父组件调用， 确认导入脱敏配置
   */
  public importAndDesensitizationTriggeringEvent() {
    this.getDataWithMask() // 重新获取预览数据
  }

  /**
   * 脱敏配置后， 根据配置， 更新预览数据
   */
  public getDataWithMask() {
    const maskData: any = []
    const tableNames = Object.keys(this.haveSetDesensitization)
    const fileNames: any = []
    this.datasetData.forEach((element: any) => {
      fileNames.push(element.fileName)
    })
    const index =
      this.datasetData.length > 0
        ? fileNames.findIndex((item: any) => item === this.activeTableFileName)
        : 0
    const table = tableNames[index]
    const columns = this.datasetData[index].newHead // 复制的新表头
    if (this.haveSetDesensitization[table]) {
      columns.forEach((item: any) => {
        maskData.push({
          dataLevelId: this.haveSetDesensitization[table][item.name].masking
            ? this.haveSetDesensitization[table][item.name].dataLevelId
            : null,
          dataMaskingType: this.haveSetDesensitization[table][item.name].masking
            ? this.haveSetDesensitization[table][item.name].dataMaskingType
            : null,
          importColumn: this.haveSetDesensitization[table][item.name]
            .importColumn,
          name: item.name,
          semantic: item.semantic || item.recommendSemantic,
          type: item.type,
        })
      })
    }
    const passData = {
      baseTableConfigVO: {
        data: maskData,
      },
      colData: this.datasetData[index].data,
    }
    // 设置脱敏后， 将加密后的数据预览显示， <表格文件>
    DataUploadStore.generateMask(passData).then((response) => {
      const { currentHead, currentNewHead } = this.comparingConfigHistory(
        index,
        response.data.result
      )
      this.previewedDatasetOfTable[index].head = currentHead
      this.previewedDatasetOfTable[index].newHead = currentNewHead
      this.previewedDatasetOfTable[index].data = response.data.result.data
    })
  }

  /**
   * 对比配置历史， 数据类型和语义
   */
  public comparingConfigHistory(index: number, result: any) {
    const lastTimeHead: any = cloneDeep(
      this.previewedDatasetOfTable[index].head
    ) // 上一次的 head
    const lastTimeNewHead: any = cloneDeep(
      this.previewedDatasetOfTable[index].newHead
    ) // 上一次的 newHead
    const { head } = result
    const currentHead: any[] = head.map((item: any) => {
      const findFormLastTimeHead: any = lastTimeHead.find(
        (item2: any) => item2.name === item.name
      )
      if (findFormLastTimeHead) {
        return findFormLastTimeHead
      }
      return item
    })
    const currentNewHead: any[] = head.map((item: any) => {
      const findFormLastTimeNewHead: any = lastTimeNewHead.find(
        (item2: any) => item2.name === item.name
      )
      if (findFormLastTimeNewHead) {
        return findFormLastTimeNewHead
      }
      return item
    })
    return { currentHead, currentNewHead }
  }
}
</script>
<style lang="less" scoped>
.table-data-preview {
  //max-height: 505px;
}
</style>
